home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / umddvi / lib / pxlfont.c < prev    next >
C/C++ Source or Header  |  1990-10-01  |  7KB  |  302 lines

  1. /*
  2.  * Copyright (c) 1987 University of Maryland Department of Computer Science.
  3.  * All rights reserved.  Permission to copy for any purpose is hereby granted
  4.  * so long as this copyright notice remains intact.
  5.  */
  6.  
  7. #ifndef lint
  8. static char rcsid[] = "$Header: pxlfont.c,v 2.4 87/06/16 18:28:39 chris Exp $";
  9. #endif
  10.  
  11. #include <stdio.h>
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <errno.h>
  15. #include "types.h"
  16. #include "font.h"
  17. #include "fio.h"
  18.  
  19. /*
  20.  * PXL font operations.
  21.  */
  22. int    pxl_read(), pxl_getgly(), pxl_rasterise(), pxl_freefont();
  23.  
  24. struct    fontops pxlops =
  25.     { "pxl", 5.0, pxl_read, pxl_getgly, pxl_rasterise, pxl_freefont };
  26.  
  27. /*
  28.  * Local info.
  29.  */
  30. #define    PXLID    1001        /* ID denoting PXL files */
  31. #define    TAILSIZE (517 * 4)    /* size of pxl tail info */
  32.  
  33. /*
  34.  * pc describes one PXL character information block.
  35.  */
  36. struct pc {
  37.     i16    pc_width;    /* character width (pixels) */
  38.     i16    pc_height;    /* character height (pixels) */
  39.     i16    pc_xoffset;    /* X offset of reference point */
  40.     i16    pc_yoffset;    /* Y offset of reference point */
  41.     i32    pc_rastoff;    /* raster offset */
  42.     i32    pc_TFMwidth;    /* TFM width (FIXes) */
  43. };
  44.  
  45. /*
  46.  * pxl_details are the PXL-specific font details.
  47.  *
  48.  * We keep track of the number of characters converted to internal
  49.  * glyph form, and when all have been done, we discard the now-
  50.  * useless details.
  51.  */
  52. struct pxl_details {
  53.     int    pd_nconv;    /* number of characters converted */
  54.     char    *pd_ras;    /* raster space, until converted */
  55.     struct    pc pd_pc[128];    /* `font directory' */
  56. };
  57.  
  58. /*
  59.  * Get the pxl_details from font f.
  60.  */
  61. #define    ftopd(f) ((struct pxl_details *) (f)->f_details)
  62.  
  63. extern    errno;
  64. char    *malloc();
  65.  
  66. /*
  67.  * Read a PXL file.
  68.  */
  69. static int
  70. pxl_read(f)
  71.     struct font *f;
  72. {
  73.     register struct pxl_details *pd;
  74.     register FILE *fp;
  75.     register struct pc *pc;
  76.     register int i;
  77.     int fd, saverr;
  78.     i32 pxlid;
  79.     struct stat st;
  80.  
  81.     if ((fd = open(f->f_path, 0)) < 0)
  82.         return (-1);
  83.  
  84.     fp = NULL;
  85.     if ((pd = (struct pxl_details *) malloc(sizeof (*pd))) == 0)
  86.         goto fail;
  87.     pd->pd_ras = 0;
  88.  
  89.     /*
  90.      * There should be 4n bytes, with an absolute minimum of TAILSIZE+4
  91.      * (+4 for the initial PXLID).
  92.      */
  93.     (void) fstat(fd, &st);
  94.     if ((st.st_size & 3) != 0 || st.st_size < (TAILSIZE + 4)) {
  95.         errno = EINVAL;
  96.         goto fail;
  97.     }
  98.  
  99.     /*
  100.      * Set up the raster pointer (if we need rasters).
  101.      */
  102.     if (f->f_flags & FF_RASTERS) {
  103.         i = st.st_size - (TAILSIZE + 4);
  104.         if (i != 0)  {
  105.             if ((pd->pd_ras = malloc((unsigned) i)) == 0)
  106.                 goto fail;
  107.             (void) lseek(fd, 4L, 0);
  108.             if (read(fd, pd->pd_ras, i) != i)
  109.                 goto fail;
  110.         }
  111.     }
  112.  
  113.     /*
  114.      * Read the glyph information.
  115.      */
  116.     errno = 0;        /* try to make errno meaningful */
  117.     if ((fp = fdopen(fd, "r")) == NULL) {
  118.         if (errno == 0)
  119.             errno = EMFILE;
  120.         goto fail;
  121.     }
  122.     (void) fseek(fp, (long) -TAILSIZE, 2);
  123.     for (i = 128, pc = pd->pd_pc; --i >= 0; pc++) {
  124.         fGetWord(fp, pc->pc_width);
  125.         fGetWord(fp, pc->pc_height);
  126.         fGetWord(fp, pc->pc_xoffset);
  127.         fGetWord(fp, pc->pc_yoffset);
  128.         fGetLong(fp, pc->pc_rastoff);
  129.         fGetLong(fp, pc->pc_TFMwidth);
  130.     }
  131.     f->f_checksum = GetLong(fp);
  132.     (void) GetLong(fp);    /* mag */
  133.     (void) GetLong(fp);    /* designsize */
  134.     (void) GetLong(fp);    /* dirpointer */
  135.     pxlid = GetLong(fp);
  136.     if (pxlid != PXLID)
  137.         error(0, 0, "Warning: strange PXL id (%d) in \"%s\"",
  138.             pxlid, f->f_path);
  139.  
  140.     f->f_details = (char *) pd;
  141.     if (FontHasGlyphs(f, 0, 128))
  142.         goto fail;
  143.     (void) fclose(fp);
  144.     pd->pd_nconv = 0;
  145.     return (0);
  146.  
  147. fail:
  148.     saverr = errno;
  149.     if (pd) {
  150.         if (pd->pd_ras)
  151.             free(pd->pd_ras);
  152.         free((char *) pd);
  153.     }
  154.     if (fp)
  155.         (void) fclose(fp);
  156.     else
  157.         (void) close(fd);
  158.     errno = saverr;
  159.     return (-1);
  160. }
  161.  
  162. /*
  163.  * Obtain the specified range of glyphs.
  164.  */
  165. static int
  166. pxl_getgly(f, l, h)
  167.     register struct font *f;
  168.     int l;
  169.     register int h;
  170. {
  171.     register struct glyph *g;
  172.     register struct pc *pc;
  173.     register int i;
  174.     struct pxl_details *pd;
  175.  
  176.     if ((pd = ftopd(f)) == NULL)
  177.         error(1, 0, "pxl_getgly details==0: cannot happen");
  178.     /*
  179.      * By definition, all 128 glyphs are valid.  Just copy the
  180.      * PXL information.
  181.      */
  182.     for (pc = &pd->pd_pc[i = l]; i < h; i++, pc++) {
  183.         g = f->f_gly[i];
  184.         g->g_flags = GF_VALID;
  185.         g->g_height = pc->pc_height;
  186.         g->g_width = pc->pc_width;
  187.         g->g_yorigin = pc->pc_yoffset;
  188.         g->g_xorigin = pc->pc_xoffset;
  189.         g->g_tfmwidth = pc->pc_TFMwidth;
  190.     }
  191.     return (0);
  192. }
  193.  
  194. /*
  195.  * Helper function for rasterise: return a pointer to a converted
  196.  * (malloc()ed and minimised) raster.
  197.  */
  198. static char *
  199. makeraster(h, w, rp)
  200.     register int h, w;
  201.     register char *rp;
  202. {
  203.     register char *cp;
  204.     register int i, o;
  205.     char *rv;
  206.  
  207.     /*
  208.      * The height and width values are in bits.  Convert width to
  209.      * bytes, rounding up.  The raw raster (at rp) is almost what
  210.      * we want, but not quite: it has `extra' bytes at the end of
  211.      * each row, to pad out to a multiple of four bytes.
  212.      */
  213.     w = (w + 7) >> 3;
  214.     o = (4 - w) & 3;    /* offset (number of `extra' bytes) */
  215.     if ((cp = malloc((unsigned) (h * w))) == NULL)
  216.         return (NULL);
  217.     if (o == 0) {
  218.         /*
  219.          * The raster fits exactly; just copy it to the allocated
  220.          * memory space.  (We must copy anyway, so that glyphs
  221.          * can be freed, e.g., after rotation.)
  222.          */
  223.         bcopy(rp, cp, h * w);
  224.         return (cp);
  225.     }
  226.     rv = cp;
  227.     while (--h >= 0) {
  228.         /*
  229.          * Copy each row, then skip over the extra stuff.
  230.          */
  231.         for (i = w; --i >= 0;)
  232.             *cp++ = *rp++;
  233.         rp += o;
  234.     }
  235.     return (rv);
  236. }
  237.  
  238. /*
  239.  * Obtain rasters for the specified glyphs.
  240.  */
  241. static int
  242. pxl_rasterise(f, l, h)
  243.     register struct font *f;
  244.     int l;
  245.     register int h;
  246. {
  247.     register struct glyph *g;
  248.     register struct pc *pc;
  249.     register int i;
  250.     register struct pxl_details *pd;
  251.  
  252.     if ((pd = ftopd(f)) == NULL)
  253.         error(1, 0, "pxl_rasterise details==0: cannot happen");
  254.     if (pd->pd_ras == NULL)
  255.         error(1, 0, "pxl_rasterise pd_ras==NULL: cannot happen");
  256.     for (pc = &pd->pd_pc[i = l]; i < h; i++, pc++) {
  257.         g = f->f_gly[i];
  258.         if (pc->pc_rastoff == 0) {
  259.             /*
  260.              * g should not claim a raster, since it has none.
  261.              */
  262.             if (HASRASTER(g))
  263.                 error(1, 0, "bad PXL glyph %d in \"%s\"",
  264.                     g->g_index, f->f_path);
  265.         } else {
  266.             g->g_raster = makeraster(pc->pc_height, pc->pc_width,
  267.                 pd->pd_ras + ((pc->pc_rastoff - 1) << 2));
  268.             if (g->g_raster == NULL)
  269.                 return (-1);    /* ??? */
  270.             g->g_rotation = ROT_NORM;
  271.         }
  272.     }
  273.  
  274.     /*
  275.      * If we have converted all the characters, dump the
  276.      * pre-conversion rasters.  In fact, dump everything.
  277.      */
  278.     pd->pd_nconv += h - l;
  279.     if (pd->pd_nconv == 128) {
  280.         free(pd->pd_ras);
  281.         free((char *) pd);
  282.         f->f_details = NULL;
  283.     }
  284.     return (0);
  285. }
  286.  
  287. /*
  288.  * Discard the font details.
  289.  */
  290. static
  291. pxl_freefont(f)
  292.     struct font *f;
  293. {
  294.     struct pxl_details *pd;
  295.  
  296.     if ((pd = ftopd(f)) != NULL) {
  297.         if (pd->pd_ras != NULL)
  298.             free(pd->pd_ras);
  299.         free((char *) pd);
  300.     }
  301. }
  302.